package brau.business;


import java.io.BufferedReader;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.List;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import br.gov.frameworkdemoiselle.annotation.Startup;
import br.gov.frameworkdemoiselle.stereotype.BusinessController;
import br.gov.frameworkdemoiselle.template.DelegateCrud;
import brau.domain.Endereco;
import brau.persistence.EnderecoDAO;
import brau.util.Utilitarios;

@BusinessController
public class EnderecoBC extends DelegateCrud<Endereco, Long, EnderecoDAO> {
	
	private static final long serialVersionUID = 1L;
	
	@Startup
//	@Transactional   ---  Linha comentada para não causar erro durante a intanciação do container
	public void load() {
		if (findAll().isEmpty()) {
			insert(new Endereco(null,"80020280","Rua Pdte Carlos Cavalcanti","19","Centro","Ap-888-A","Curitiba","PR","Brasil",1,-25.4268862,-49.2651005));
			insert(new Endereco(null,"80520170","R. Carlos Pioli","133","Bom Retiro","","Curitiba","PR","Brasil",1,-25.4110737,-49.2726121));
			insert(new Endereco(null,"90010390","Av. Augusto de Carvalho","1133","Centro","","Porto Alegre","RS","Brasil",1,-30.0380169,-51.2330246));
			insert(new Endereco(null,"80040310","R. Augusto Stresser","1325","Hugo Lange","","Curitiba","PR","Brasil",1,-25.417348,-49.24889569999999));
		}
	}

	
	public void gravarEnderecoGmap(Endereco end) {
		Endereco endCad = buscarEnderecoByPontoXY(end.getPontoX(), end.getPontoY());
		if (endCad == null ||  endCad.getId() == null) {
			end.setId(null);
			getDelegate().insert(end);
		} else {
			end.setId(endCad.getId());
			getDelegate().update(end);
		}
	}
	
	public List<Endereco> buscarEnderecoByFilter(String filter) {
		return getDelegate().buscarEnderecoByfilter(filter);
	}

	public Endereco buscarEnderecoByPontoXY(Double pontoX, Double pontoY) {
		return getDelegate().buscarEnderecoByPontoXY(pontoX,pontoY);
	}


	public Endereco buscarEnderecoGMapByPontoXY(Double pontoX, Double pontoY) {
		Endereco endRetorno = new Endereco();
		if (pontoX != null && pontoY != null) {
			String infoEndereco = String.valueOf(pontoX) + "," + String.valueOf(pontoY);
			endRetorno = buscarEnderecoGMap(infoEndereco);
		}
		return endRetorno;
	}
	

	public Endereco buscarEnderecoGMapByEndereco(Endereco endereco) {

		Endereco endRetorno = new Endereco();
		String infoEndereco = "";
		
		if ( ! endereco.getLogradouro().isEmpty()) {
			
			if ( ! endereco.getLogradouro().isEmpty())
				infoEndereco = Utilitarios.prepararLogradouroParaPesqGMap(endereco.getLogradouro());

			if (endereco.getNumero() != null && ! endereco.getNumero().isEmpty()) 
				infoEndereco += "," + endereco.getNumero();
			
			if (endereco.getBairro() != null && ! endereco.getBairro().isEmpty()) 
				infoEndereco += "," + Utilitarios.prepararLogradouroParaPesqGMap(endereco.getBairro());
			
			if (endereco.getLocalidade() != null && ! endereco.getLocalidade().isEmpty()) 
				infoEndereco += "," + Utilitarios.prepararLogradouroParaPesqGMap(endereco.getLocalidade());
			
			if (endereco.getUf() != null && ! endereco.getUf().isEmpty()) 
				infoEndereco += "," + endereco.getUf();
			
			endRetorno = buscarEnderecoGMap(infoEndereco);
			
		}
		return endRetorno;
	}

	
	public Endereco buscarEnderecoGMap(String infoEndereco) {

		Endereco endRetorno = new Endereco();
		
		if (infoEndereco.isEmpty()) return endRetorno;
		
		String strUrl = "http://maps.google.com/maps/geo?q=" + infoEndereco + "&output=json&sensor=false";
		
		try {
		   
			java.net.URL url = new java.net.URL(strUrl);
			
			HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
			
			urlConnection.connect();
			int rc = urlConnection.getResponseCode();

			if (rc == 200) { 
		    	  String line = null; 
		    	  BufferedReader br = new BufferedReader(new java.io.InputStreamReader(urlConnection.getInputStream())); 
		    	  StringBuilder sb = new StringBuilder(); 

		    	  while ((line = br.readLine()) != null) sb.append(line + '\n'); 
		    	  
		    	  JSONObject jsonObj = (JSONObject) JSONValue.parse(sb.toString());
		    	  
		    	  endRetorno = carregarEnderecoWithJObjGMap(jsonObj);
		      } else {
		    	  System.out.println("HTTP error:"+rc); 
		      }

			urlConnection.disconnect(); 
	         
		} catch (java.net.MalformedURLException e) {
			System.out.println("Erro ao criar URL. Formato inválido.");
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("Erro ao abrir a conexão - IOException");
			e.printStackTrace();
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return endRetorno;
	}
	
	
	public Endereco carregarEnderecoWithJObjGMap(JSONObject jsonObj ) {

		List<Endereco> listaEndGmap = new ArrayList<Endereco>();
		Endereco endRetorno = new Endereco();

		JSONArray jsonObjArray = (JSONArray)jsonObj.get("Placemark"); 

		if (jsonObjArray != null && jsonObjArray.size() > 0) {
			for (int i=0; i < jsonObjArray.size(); i++) { 
				listaEndGmap.add(tratarAddressObjectJSON((JSONObject)jsonObjArray.get(i)));
			} 
			endRetorno = listaEndGmap.get(0);
		
		} else {
			System.out.println("##  Nada Retornado ##");
		}
		
		return endRetorno;
	}

	
	private Endereco tratarAddressObjectJSON(JSONObject jsonObj) {
		
		Endereco endRetorno = new Endereco();
		
		JSONObject addressDetails = (JSONObject) ((JSONObject)jsonObj).get("AddressDetails");

		if (addressDetails != null) {

			JSONObject countryObj = (JSONObject) addressDetails.get("Country");
			if (countryObj != null) {
				String countryName = (String) countryObj.get("CountryName");
				String countryNameCode = (String) countryObj.get("CountryNameCode");
				// TODO falta colocar o país na tabela
				endRetorno.setPais(countryNameCode);
				System.out.println("country : " + countryName + " - " + countryNameCode);

				JSONObject administrativeArea = (JSONObject) countryObj.get("AdministrativeArea");
				if (administrativeArea != null) {
					String administrativeAreaName = (String) administrativeArea.get("AdministrativeAreaName");
//					Este informação deve ser preenchida como argumento necessário para esta pesquisa
					endRetorno.setUf(administrativeAreaName);
					System.out.println("administrativeAreaName : " + administrativeAreaName);

					JSONObject locality = (JSONObject)administrativeArea.get("Locality");
					if (locality != null) {
						String localityName = (String)locality.get("LocalityName");
						endRetorno.setLocalidade(localityName);
						System.out.println("localityName : " + localityName);

						JSONObject dependentLocality = (JSONObject)locality.get("DependentLocality");
						if (dependentLocality != null) {
							String dependentLocalityName = (String)dependentLocality.get("DependentLocalityName");
							System.out.println("dependentLocalityName : " +dependentLocalityName);
							endRetorno.setBairro(dependentLocalityName);

							JSONObject thoroughfare = (JSONObject)dependentLocality.get("Thoroughfare");
							if (thoroughfare != null) {
								String thoroughfareName = (String)thoroughfare.get("ThoroughfareName");
								//TODO confirmar se é aconselhável fazer isso !!
								String[] thoroughfareNameArray=thoroughfareName.split(",");
								endRetorno.setLogradouro(thoroughfareNameArray[0]);
								if (endRetorno.getNumero() == null) endRetorno.setNumero("");
								if (endRetorno.getNumero().isEmpty() && thoroughfareNameArray.length > 1 ) endRetorno.setNumero(thoroughfareNameArray[1].trim());
								System.out.println("thoroughfareName : " +thoroughfareName);
							}

							JSONObject postalCode = (JSONObject)dependentLocality.get("PostalCode");
							if (postalCode != null) {
								String postalCodeNumber = (String)postalCode.get("PostalCodeNumber");
								endRetorno.setCep(postalCodeNumber);
//								System.out.println("postalCodeNumber : " +postalCodeNumber);
		    				}
						}
					}
				}   				  
			}
		}

		JSONObject point = (JSONObject) ((JSONObject)jsonObj).get("Point"); 
		if (point != null) {
			JSONArray coordinatesArray = (JSONArray)point.get("coordinates");
			Double pX = (Double) coordinatesArray.get(1);
			Double pY = (Double) coordinatesArray.get(0);
			endRetorno.setPontoX(pX);
			endRetorno.setPontoY(pY);
		}
		return endRetorno;
	}
	
	
}
